﻿#include <hacks/net/tcp_conn.h>

namespace hacks::net {

    const std::string &tcp_conn::get_conn_id() const {
        return conn_id_;
    }

    void tcp_conn::set_conn_id(const std::string &s) {
        //disallow reset conn id
        assert(conn_id_.length() == 0);
        conn_id_ = s;
    }

    void tcp_conn::commit() {
        std::call_once(once_commit_, [this]() {
            this->loop_->run_in_loop([ins = shared_from_this()]() {
                //
                auto sock_fd = mk_ev_sock_fd(ins->loop_,
                                             ins->sock_fd_,
                                             std::bind(&tcp_conn::conn_rw_handler,
                                                       ins.get(),
                                                       std::placeholders::_1,
                                                       std::placeholders::_2,
                                                       std::placeholders::_3),
                                             std::bind(&tcp_conn::conn_closed_handler,
                                                       ins.get(),
                                                       std::placeholders::_1));
                //commit sockfd
                ins->shd_sock_fd_.swap(sock_fd);
                ins->shd_sock_fd_->commit();
            });
        });
    }

    void tcp_conn::async_write(const_buffer &&data) {
        loop_->run_in_loop(
                [data = std::move(data), ins = shared_from_this()]() mutable {
                    const auto &sock_fd = ins->shd_sock_fd_;
                    if (sock_fd->get_status() != evt_commited) {
                        return;
                    }
                    ins->const_buffers_.emplace_back(std::move(data));
                    sock_fd->update_event(ev_event_readable | ev_event_writeable);
                });
    }

    tcp_conn::tcp_conn(const shared_ev_loop &loop, ev_os_sock_t fd)
            : loop_(loop),
              sock_fd_(fd),
              shd_sock_fd_(nullptr),
              const_buffers_(),
              once_commit_(),
              conn_id_(),
              accept_functor_(nullptr),
              data_functor_(nullptr),
              closed_functor_(nullptr) {
    }

    void tcp_conn::set_accept_callback(conn_new_functor_t &&f) {
        accept_functor_ = std::move(f);
    }

    void tcp_conn::set_data_callback(conn_data_functor_t &&f) {
        data_functor_ = std::move(f);
    }

    void tcp_conn::set_closed_callback(conn_closed_functor_t &&f) {
        closed_functor_ = std::move(f);
    }

    void tcp_conn::on_accepted() {
        //todo ssl_set_accept

    }
}
